#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "v_list.h"

static vd_list_node_t* vd_create_node(vc_data_ptr_t data_ptr, uint32_t data_size)
{
    vd_list_node_t* node = (vd_list_node_t*)v_malloc(sizeof(vd_list_node_t));
    if (node == NULL) {
        return NULL;
    }

    node->data_ptr = (v_data_ptr_t)v_malloc(data_size);
    if (node->data_ptr == NULL) {
        v_free(node);
        return NULL;
    }

    memcpy(node->data_ptr, data_ptr, data_size);
    return node;
}

static vlib_status_t vd_insert(vd_list_ptr_t list, vd_list_node_t* position, vc_data_ptr_t data_ptr, uint32_t data_size)
{
    if (data_size != list->type_size) {
        return VLIB_ERROR;
    }

    vd_list_node_t* node = vd_create_node(data_ptr, data_size);
    if (node == NULL) {
        return VLIB_ERROR;
    }

    node->next = position->next;
    position->next->prev = node;
    node->prev = position;
    position->next = node;
    if (node->next == &list->head) {     //如果容器为空, 则让头结点数据指针指向这一个节点
        list->head.data_ptr = node->data_ptr;   //作为判断容器是否为空的依据
    }

    ++list->list_size;

    return VLIB_OK;
}

static void vd_delete(vd_list_ptr_t list, vd_list_node_t* position)
{
    if (list->list_size == 0){
        return;
    }
    
    if (position->next == &list->head) {    //如果为最后一个节点
        if (list->head.data_ptr != position->prev->data_ptr) {    //如果有至少两个节点
            list->head.data_ptr = position->prev->data_ptr;
        } else {                            //如果只有一个节点
            list->head.data_ptr = list->null_data_ptr;         //确保容器为空时正常访问
        }
    }
    position->prev->next = position->next;
    position->next->prev = position->prev;

    v_free(position->data_ptr);
    v_free(position);

    --list->list_size;
}

/*=======================
 * Getter functions
 *======================*/

v_data_ptr_t vd_list_back(vd_list_ptr_t list)
{
    return list->head.prev->data_ptr;
}

v_data_ptr_t vd_list_front(vd_list_ptr_t list)
{
    return list->head.next->data_ptr;
}

vd_list_it_ptr_t vd_list_begin(vd_list_ptr_t list)
{
    return list->head.next;
}

vd_list_it_ptr_t vd_list_end(vd_list_ptr_t list)
{
    return &list->head;
}

bool vd_list_empty(vd_list_ptr_t list)
{
    return (list->list_size == 0);
}

uint32_t vd_list_size(vd_list_ptr_t list)
{
    return list->list_size;
}

/*=====================
 * Setter functions
 *====================*/

void vd_list_insert(vd_list_ptr_t list, vd_list_it_ptr_t position, vc_data_ptr_t data_ptr, uint32_t data_size)
{
    vd_insert(list, position->prev, data_ptr, data_size);
}

void vd_list_push_back(vd_list_ptr_t list, vc_data_ptr_t data_ptr, uint32_t data_size)
{
    vd_insert(list, list->head.prev, data_ptr, data_size);
}

void vd_list_push_front(vd_list_ptr_t list, vc_data_ptr_t data_ptr, uint32_t data_size)
{
    vd_insert(list, list->head.next, data_ptr, data_size);
}

void vd_list_pop_back(vd_list_ptr_t list)
{
    vd_delete(list, list->head.prev);
}

void vd_list_pop_front(vd_list_ptr_t list)
{
    vd_delete(list, list->head.next);
}

void vd_list_clear(vd_list_ptr_t list)
{
    while (!vd_list_empty(list)) {
        vd_delete(list, list->head.next);
    }
}

/*=======================
 * Other functions
 *======================*/

/* 迭代器 */
v_data_ptr_t vd_list_iter_data(vd_list_it_ptr_t iter)
{
    return iter->data_ptr;
}

void vd_list_iter_forward(vd_list_it_ptr_t *iter)
{
    *iter = (*iter)->next;
}

void vd_list_iter_forward_to(vd_list_it_ptr_t *iter, int step)
{
    while(step) {
        vd_list_iter_forward(iter);
        --step;
    }
}

void vd_list_iter_backward(vd_list_it_ptr_t *iter)
{
    *iter = (*iter)->prev;
}

void vd_list_iter_backward_to(vd_list_it_ptr_t *iter, int step)
{
    while(step) {
        vd_list_iter_backward(iter);
        --step;
    }
}

/**********************
 *   GLOBAL FUNCTIONS
 **********************/

vd_list_ptr_t vd_list_create(uint32_t type_size)
{
    vd_list_ptr_t list = (vd_list_ptr_t)v_malloc(sizeof(vd_list_t));
    if (list == NULL) {
        return NULL;
    }
    list->null_data_ptr = (v_data_ptr_t)v_malloc(type_size);
    if (list->null_data_ptr == NULL) {
        return NULL;
    }
    memset(list->null_data_ptr, '\0', type_size);

    list->list_size = 0;
    list->type_size = type_size;
    list->head.prev = &list->head;
    list->head.next = &list->head;
    list->head.data_ptr = list->null_data_ptr;      //确保在容器为空时正常访问

    return list;
}

void vd_list_destroy(vd_list_ptr_t list)
{
    vd_list_clear(list);
    v_free(list->null_data_ptr);
    v_free(list);
}
